package com.zfei.gfb.controller;

import com.google.common.collect.Lists;
import com.zfei.gfb.api.StatsService;
import com.zfei.gfb.api.TalkService;
import com.zfei.gfb.api.domain.StatsTag;
import com.zfei.gfb.bean.Const;
import com.zfei.gfb.bean.Result;
import com.zfei.gfb.core.Auth;
import com.zfei.gfb.core.Dynamic;
import com.zfei.gfb.core.HttpJson;
import com.zfei.gfb.core.LogResult;
import com.zfei.gfb.dao.GfbBannerMapper;
import com.zfei.gfb.dao.GfbGoodsMapper;
import com.zfei.gfb.dao.GfbHouseApplyMapper;
import com.zfei.gfb.dao.GfbHouseMapper;
import com.zfei.gfb.query.GfbGoodsQuery;
import com.zfei.gfb.query.GfbHouseApplyQuery;
import com.zfei.gfb.query.GfbHouseQuery;
import com.zfei.gfb.query.h5.StateGoodsQuery;
import com.zfei.gfb.vo.StatsVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author
 * @version 1.0
 */
@Api(tags = "后台统计接口")
@RestController
@RequestMapping("/web")
public class GfbStatsController {

    private static final Logger logger = LoggerFactory.getLogger(GfbStatsController.class);

    private final Executor executor = new ThreadPoolExecutor(10, 50, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(50));


    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private StatsService statsService;

    @Resource
    private GfbHouseMapper gfbHouseMapper;

    @Resource
    private GfbHouseApplyMapper gfbHouseApplyMapper;

    @Resource
    private GfbGoodsMapper gfbGoodsMapper;

    @ApiOperation(value = "数据面板")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = StatsVo.class),
    })
    @LogResult
    @HttpJson("/stats")
    public Object stats() throws IllegalAccessException, InterruptedException {

        StatsVo statsVo = new StatsVo();
        //house
//        computeHouse(statsVo);
        //乡村集市物品总数  //
//        StatsVo.GoodsStats goodsStats = (StatsVo.GoodsStats) ((Result) statsGoods(new StateGoodsQuery())).getData();
//        statsVo.setGoods(goodsStats);

        List<Runnable> tasks = Lists.newArrayList();

        Field[] all = StatsVo.class.getDeclaredFields();
        for (Field field : all) {
            field.setAccessible(true);
            Object subStatsVo = field.get(statsVo);

            if (subStatsVo == null) {
                logger.error("StatsVo属性不存在");
                continue;
            }
            Class<?> subStatsVoClass = subStatsVo.getClass();
            Dynamic tableDyn = subStatsVoClass.getAnnotation(Dynamic.class);
            String tableSql = "";
            if (tableDyn == null || StringUtils.isBlank(tableDyn.value())) {
                logger.warn("查询表级sql不存在");
            } else {
                tableSql = tableDyn.value();
            }
            Field[] subFields = subStatsVoClass.getDeclaredFields();
            for (Field subField : subFields) {
                Dynamic dynamicAnno = subField.getAnnotation(Dynamic.class);
                String fullSql;
                if (dynamicAnno == null) {
                    //查总数
                    fullSql = tableSql;
                } else {
                    String subSql = dynamicAnno.value();
                    if (dynamicAnno.useParSql()) {
                        //是否复用父sql
                        fullSql = tableSql + " where " + subSql;
                    } else {
                        fullSql = subSql;
                    }
                }
                if (StringUtils.isBlank(fullSql)) {
                    logger.warn("空sql");
                    continue;
                }
                Runnable runnable = () -> {
                    Integer num = jdbcTemplate.queryForObject(fullSql, Integer.class);
                    subField.setAccessible(true);
                    try {
                        subField.set(subStatsVo, num);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                };
                tasks.add(runnable);
            }
        }

        if (tasks.size() > 0) {
            CountDownLatch latch = new CountDownLatch(tasks.size());
            for (Runnable task : tasks) {
                executor.execute(
                        () -> {
                            task.run();
                            latch.countDown();
                        }
                );
            }
            latch.await(3000L, TimeUnit.MILLISECONDS);
        }

        return statsVo;
    }

    @ApiOperation(value = "乡村集市数据面板")
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = StatsVo.GoodsStats.class),
    })
    @LogResult
    @HttpJson("/goods/stats")
    public Object statsGoods(@RequestBody StateGoodsQuery query) throws InterruptedException {

        String villagerName = query.getVillagerName();
        //(其中，区域选择中展示某村的乡村集市的物品信息）
        StatsVo.GoodsStats subStatsVo = new StatsVo.GoodsStats();

        List<Runnable> tasks = Lists.newArrayList();

        Class<?> subStatsVoClass = subStatsVo.getClass();
        Dynamic tableDyn = subStatsVoClass.getAnnotation(Dynamic.class);
        String tableSql = "";
        if (tableDyn == null || StringUtils.isBlank(tableDyn.value())) {
            logger.warn("查询表级sql不存在");
        } else {
            tableSql = tableDyn.value();
        }
        Field[] subFields = subStatsVoClass.getDeclaredFields();
        for (Field subField : subFields) {
            Dynamic dynamicAnno = subField.getAnnotation(Dynamic.class);
            String fullSql;
            if (dynamicAnno == null) {
                //查总数
                if (villagerName == null) {
                    fullSql = tableSql;
                }else {
                    fullSql = tableSql + "where villager_name = '" + villagerName + "'";
                }
            } else {
                String subSql = dynamicAnno.value();
                if (dynamicAnno.useParSql()) {
                    //是否复用父sql
                    if (villagerName == null) {
                        fullSql = tableSql + " where " + subSql;
                    } else {
                        fullSql = tableSql + " where " + subSql + " and villager_name = '" + villagerName + "'";
                    }

                } else {
                    if(dynamicAnno.isAppend()){
                        if (villagerName == null) {
                            fullSql = subSql;
                        } else {
                            fullSql = subSql + " and villager_name = '" + villagerName + "'";
                        }
                    }else {
                        fullSql = subSql;
                    }
                }
            }

            if (StringUtils.isBlank(fullSql)) {
                logger.warn("空sql");
                continue;
            }
            Runnable runnable = () -> {
                Integer num = jdbcTemplate.queryForObject(fullSql, Integer.class);
                subField.setAccessible(true);
                try {
                    subField.set(subStatsVo, num);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            };
            tasks.add(runnable);
        }

        if (tasks.size() > 0) {
            CountDownLatch latch = new CountDownLatch(tasks.size());
            for (Runnable task : tasks) {
                executor.execute(
                        () -> {
                            task.run();
                            latch.countDown();
                        }
                );
            }
            latch.await(3000L, TimeUnit.MILLISECONDS);
        }

        return subStatsVo;
    }
}
